package alp.starcode.nudtportal.framework.aspect;

import alp.starcode.common.result.Result;
import alp.starcode.nudtportal.framework.constant.CodeConst;
import alp.starcode.nudtportal.framework.constant.ProjectConst;
import alp.starcode.nudtportal.framework.util.SM2Utils;
import alp.starcode.nudtportal.framework.util.SignUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;


@Aspect
@Configuration
@Slf4j
public class CheckSignAspect {


    private static long expireTime = 60 * 15 * 1000;//接口签名验证超时时间 15分钟

    // 定义切点Pointcut
    @Pointcut("@annotation(alp.starcode.nudtportal.framework.aspect.model.CheckSign)")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("开始验证签名");
            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = Objects.requireNonNull(sra).getRequest();

            String timestamp = request.getHeader("ts");//获取ts时间戳参数
            String sign = request.getHeader("sign");//获取sign参数
            String nonce = request.getHeader("nonce");//获取nonce随机字符串参数
            String token = request.getHeader("id_token");//获取token参数
            String key = request.getHeader("key");//获取加密key参数
            if (StrUtil.isBlank(timestamp) || StrUtil.isBlank(sign)) {
                log.error("验证签名失败：timestamp和sign参数为空");
                return Result.error(CodeConst.SIGN_ERROR);
            }
            long requestTime = Long.valueOf(timestamp);
            long now = System.currentTimeMillis();
            log.info("now={}", now);
            // 请求发起时间与当前时间超过expireTime，则接口请求过期
            if (now - requestTime > expireTime) {
                log.error("验证签名失败：接口请求过期");
                return Result.error(CodeConst.SIGN_ERROR);
            }
            //对key解密
            String secretKey = SM2Utils.decrypt(ProjectConst.PRIVATE_KEY, key);
            String generatedSign = SignUtil.sign(request, secretKey, timestamp, nonce, token);
            if (!generatedSign.equals(sign)) {
                log.error("验证签名失败：签名校验错误" + generatedSign);
                return Result.error(CodeConst.SIGN_ERROR);
            }

            Object result = joinPoint.proceed();
            return result;


    }
}
